package com.bins.dentist.clinic.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bins.dentist.clinic.constants.CommonConstants;
import com.bins.dentist.clinic.mapper.PermissionMapper;
import com.bins.dentist.clinic.model.dto.PermissionDto;
import com.bins.dentist.clinic.model.dto.PermissionPageDto;
import com.bins.dentist.clinic.model.dto.RolePermDto;
import com.bins.dentist.clinic.entity.PermissionEntity;
import com.bins.dentist.clinic.entity.RolePermissionEntity;
import com.bins.dentist.clinic.model.vo.PermissionTreeVo;
import com.bins.dentist.clinic.model.vo.PermissionVo;
import com.bins.dentist.clinic.service.PermissionService;
import com.bins.dentist.clinic.service.RolePermissionService;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author bins
 * @since 2023-02-20 20:53:31
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, PermissionEntity> implements PermissionService {

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private RolePermissionService rolePermissionService;

    @Override
    public IPage<PermissionVo> getPage(PermissionPageDto pageDto) {
        LambdaQueryWrapper<PermissionEntity> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(!ObjectUtils.isEmpty(pageDto.getPermissionCode()), PermissionEntity::getPermissionCode, pageDto.getPermissionCode())
                .like(!ObjectUtils.isEmpty(pageDto.getPermissionName()), PermissionEntity::getPermissionName, pageDto.getPermissionName())
                .eq(PermissionEntity::getIsDel, CommonConstants.DELETED_NO);
        IPage page = permissionMapper.selectPage(new Page(pageDto.getPageNum(), pageDto.getPageSize()), queryWrapper);
        List<PermissionEntity> permissionPageList = page.getRecords();
        if (CollectionUtils.isEmpty(permissionPageList)) {
            return page;
        }
        List<PermissionVo> resultList = Lists.newArrayListWithCapacity(permissionPageList.size());
        for (PermissionEntity deptEntity : permissionPageList) {
            PermissionVo permissionVo = new PermissionVo();
            BeanUtils.copyProperties(deptEntity, permissionVo);
            resultList.add(permissionVo);
        }
        page.setRecords(resultList);
        return page;
    }

    @Override
    public PermissionVo getDetailById(PermissionDto dto) {
        PermissionEntity permissionEntity = permissionMapper.selectById(dto.getId());
        PermissionVo vo = new PermissionVo();
        BeanUtils.copyProperties(permissionEntity, vo);
        return vo;
    }

    @Override
    public PermissionVo savePermission(PermissionDto dto) {
        PermissionEntity entity = new PermissionEntity();
        if (ObjectUtils.isEmpty(dto.getId())) {
            BeanUtils.copyProperties(dto, entity);
            entity.setPid(ObjectUtils.isEmpty(dto.getPid()) ? 0 : dto.getPid());
            entity.setIsDel(CommonConstants.DELETED_NO);
            entity.setCreateBy(0L);
            entity.setUpdateBy(0L);
            entity.setCreateTime(LocalDateTime.now());
            entity.setUpdateTime(LocalDateTime.now());
            permissionMapper.insert(entity);
        } else {
            entity.setId(dto.getId());
            entity.setPermissionCode(dto.getPermissionCode());
            entity.setPermissionName(dto.getPermissionName());
            entity.setPid(ObjectUtils.isEmpty(dto.getPid()) ? 0 : dto.getPid());
            entity.setUpdateBy(999999L);
            entity.setUpdateTime(LocalDateTime.now());
            permissionMapper.updateById(entity);
        }
        PermissionVo vo = new PermissionVo();
        vo.setId(entity.getId());
        vo.setPermissionCode(entity.getPermissionCode());
        vo.setPermissionName(entity.getPermissionName());
        return vo;
    }

    @Override
    public Integer deletePermission(PermissionDto dto) {
        PermissionEntity entity = new PermissionEntity();
        entity.setId(dto.getId());
        entity.setIsDel(CommonConstants.DELETED_YES);
        return permissionMapper.updateById(entity);
    }

    @Override
    public List<PermissionTreeVo> permTreeList() {
        List<PermissionEntity> allList = findAll();
        if (CollectionUtils.isEmpty(allList)) {
            return Collections.emptyList();
        }
        List<PermissionEntity> firstList = allList.stream().filter(s -> (!ObjectUtils.isEmpty(s.getLevel()) && s.getLevel() == 0)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(firstList)) {
            return Collections.emptyList();
        }
        List<PermissionEntity> secondList = allList.stream().filter(s -> (!ObjectUtils.isEmpty(s.getLevel()) && s.getLevel() == 1)).collect(Collectors.toList());
        Map<Integer, List<PermissionEntity>> pidMap = secondList.stream().collect(Collectors.groupingBy(PermissionEntity::getPid));
        List<PermissionTreeVo> resultList = Lists.newArrayListWithCapacity(firstList.size());
        PermissionTreeVo menuTreeVo;
        for (PermissionEntity first :firstList) {
            menuTreeVo = new PermissionTreeVo();
            menuTreeVo.setId(first.getId());
            menuTreeVo.setLabel(first.getPermissionName());
            List<PermissionEntity> pidSecondList = pidMap.get(first.getId());
            if (CollectionUtils.isEmpty(pidSecondList)) {
                resultList.add(menuTreeVo);
                continue;
            }
            PermissionTreeVo secondMenuTreeVo;
            List<PermissionTreeVo> secondResultList = Lists.newArrayListWithCapacity(pidSecondList.size());
            for (PermissionEntity second : pidSecondList) {
                secondMenuTreeVo = new PermissionTreeVo();
                secondMenuTreeVo.setId(second.getId());
                secondMenuTreeVo.setLabel(second.getPermissionName());
                secondResultList.add(secondMenuTreeVo);
            }
            menuTreeVo.setChildren(secondResultList);
            resultList.add(menuTreeVo);
        }
        return resultList;
    }

    @Override
    public List<PermissionEntity> findAll() {
        LambdaQueryWrapper<PermissionEntity> queryWrapper = new LambdaQueryWrapper<>();
        return permissionMapper.selectList(queryWrapper);
    }

    @Override
    public Integer bindRole(RolePermDto dto) {
        List<Long> permIds = dto.getPermIds();
        if (CollectionUtils.isEmpty(permIds)) {
            return 0;
        }
        List<Long> originPermIds = rolePermissionService.getIdsByRoleId(dto.getRoleId());
        permIds.removeAll(originPermIds);
        if (CollectionUtils.isEmpty(permIds)) {
            return 0;
        }
        RolePermDto rolePermDto = new RolePermDto();
        rolePermDto.setRoleId(dto.getRoleId());
        rolePermDto.setPermIds(permIds);
        List<RolePermissionEntity> perms = rolePermissionService.buildRolePermList(rolePermDto);
        rolePermissionService.saveBatch(perms);
        return perms.size();
    }
}
